﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

public struct AssetsInfo
{
    public string key;
    public string value;
    public string name;
    public int len;
}
public class AssetsChecker
{
    public struct AssetsSection
    {
        public string Name;
        public List<AssetsInfo> assets;
    }
    public struct AssetsPart
    {
        public int Length;
        public List<AssetsSection> Result;
    }
    public AssetsPart[] Parts;
    int _pos;
    public int Pos { get => _pos; }
    int _len;
    public int Length { get => _len; }
    public bool Done { get; private set; }
    public int maxLength;
    bool m_one;
    string m_assetsFolder;
    public string RootSection;
    public string IgnoreSection;
    public async void CheckAsync(INIReader all,INIReader buildIn,string assetsFolder,Action<AssetsChecker> callBack)
    {
        m_assetsFolder = assetsFolder;
        Done = false;
        await Task.Run(()=> {
            try
            {
                var secs = all.sections;
                for (int i = 0; i < secs.Count; i++)
                {
                    var sec = secs[i];
                    if (sec.Name != IgnoreSection)
                    {
                        _len += sec.Values.Count;
                    }
                }
                m_one = true;

                List<string[]> parts = LoadPartsRecord();
                if (parts.Count > 1)
                {
                    Parts = new AssetsPart[parts.Count];
                    for (int i = 0; i < Parts.Length; i++)
                        Parts[i].Result = new List<AssetsSection>();
                    m_one = false;
                }
                else
                {
                    Parts = new AssetsPart[1];
                    Parts[0].Result = new List<AssetsSection>();
                }

                for (int i = 0; i < secs.Count; i++)
                {
                    var sec = secs[i];
                    if (sec.Name != IgnoreSection)
                    {
                        for (int k = 0; k < Parts.Length; k++)
                        {
                            AssetsSection section = new AssetsSection();
                            section.assets = new List<AssetsInfo>();
                            section.Name = sec.Name;
                            Parts[k].Result.Add(section);
                        }
                        INISection bi = null;
                        if (buildIn != null)
                            bi = buildIn.FindSection(sec.Name);
                        CheckSection(i, sec, bi, parts);
                    }
                }
                Done = true;
            }catch(Exception ex)
            {
                UnityEngine.Debug.Log(ex.StackTrace);
            }
        });
        if(callBack!=null)
        {
            callBack(this);
        }
    }
    List<string[]> LoadPartsRecord()
    {
        List<string[]> parts = new List<string[]>();
        try
        {
            if (LocalSetting.firstPack != null && LocalSetting.firstPack != "")
            {
                string packPath = LocalSetting.RecordPath + "/" + LocalSetting.firstPack + ".txt";
                string[] lines = File.ReadAllText(packPath).Split('\n');
                for (int i = 0; i < lines.Length; i++)
                {
                    string str = lines[i];
                    if (str != null && str != "")
                    {
                        string[] ss = str.Split('=');
                        if (ss.Length > 1)
                        {
                            parts.Add(ss[1].Split(','));
                        }
                    }
                }
            }
        }catch(Exception ex)
        {
            UnityEngine.Debug.LogError(ex.StackTrace);
        }
        return parts;
    }
    void CheckSection(int sIndex, INISection section,INISection buildIn,List<string[]> parts)
    {
        string sn = section.Name + "/";
        if (section.Name == RootSection)
        {
            sn = "";
        }
        string assetsFolder = m_assetsFolder + sn;
        var values = section.Values;
        if(m_one)
        {
            if(buildIn!=null)
            {
                for (int i = 0; i < values.Count; i++)
                {
                    var kv = values[i];
                    if (kv.value != buildIn.GetValue(kv.key))
                    {
                        CheckKeyValue(kv, Parts[0].Result[sIndex].assets,assetsFolder, ref Parts[0].Length);
                    }
                    _pos++;
                }
            }
            else
            {
                for (int i = 0; i < values.Count; i++)
                {
                    var kv = values[i];
                    CheckKeyValue(kv, Parts[0].Result[sIndex].assets, assetsFolder, ref Parts[0].Length);
                    _pos++;
                }
            }
        }
        else
        {
            int max = Parts.Length - 1;
            if (buildIn != null)
            {
                if(sn=="")
                {
                    for (int i = 0; i < values.Count; i++)
                    {
                        var kv = values[i];
                        if (kv.value != buildIn.GetValue(kv.key))
                        {
                            List<AssetsInfo> list = Parts[0].Result[sIndex].assets;
                            CheckKeyValue(kv, list, assetsFolder, ref Parts[0].Length);
                        }
                        _pos++;
                    }
                }
                else
                {
                    for (int i = 0; i < values.Count; i++)
                    {
                        var kv = values[i];
                        if (kv.value != buildIn.GetValue(kv.key))
                        {
                            string key = sn + kv.key;
                            int index = max;
                            List<AssetsInfo> list = Parts[index].Result[sIndex].assets;
                            for (int j = 0; j < parts.Count; j++)
                            {
                                if (parts[j].Contains(key))
                                {
                                    list = Parts[j].Result[sIndex].assets;
                                    index = j;
                                    break;
                                }
                            }
                            CheckKeyValue(kv, list, assetsFolder, ref Parts[index].Length);
                        }
                        _pos++;
                    }
                }
            }
            else
            {
                if(sn=="")
                {
                    for (int i = 0; i < values.Count; i++)
                    {
                        var kv = values[i];
                        List<AssetsInfo> list = Parts[0].Result[sIndex].assets;
                        CheckKeyValue(kv, list, assetsFolder, ref Parts[0].Length);
                        _pos++;
                    }
                }
                else
                {
                    for (int i = 0; i < values.Count; i++)
                    {
                        var kv = values[i];
                        string key = sn + kv.key;
                        int index = max;
                        List<AssetsInfo> list = Parts[index].Result[sIndex].assets;
                        for (int j = 0; j < parts.Count; j++)
                        {
                            if (parts[j].Contains(key))
                            {
                                list = Parts[j].Result[sIndex].assets;
                                index = j;
                                break;
                            }
                        }
                        CheckKeyValue(kv, list, assetsFolder, ref Parts[index].Length);
                        _pos++;
                    }
                }
            }
        }
    }
    void CheckKeyValue(KeyValue kv, List<AssetsInfo> assets,string assetsFolder, ref int length)
    {
        string[] ss = kv.value.Split(';');
        string path = assetsFolder + ss[0];
        int len = 0;
        int.TryParse(ss[1], out len);
        var info = new FileInfo(path);

        if (!info.Exists || len != info.Length)
        {
            AssetsInfo ai = new AssetsInfo();
            ai.key = kv.key;
            ai.value = kv.value;
            ai.name = ss[0];
            ai.len = len;
            assets.Add(ai);
            length += len;
            maxLength += len;
        }
    }
}